#pragma once
namespace graph_basic
{
   inline void vertex_iterator_t::operator ++ ()
   {
      ++it_;
   }
   inline vertex_t const & vertex_iterator_t::operator * () const
   {
      return *it_;
   }
   inline vertex_t& vertex_iterator_t::operator * ()
   {
      return *it_;
   }
   inline bool vertex_iterator_t::operator != (vertex_iterator_t const & right) const
   {
      return it_ != right.it_;
   }
   inline bool vertex_iterator_t::operator == (vertex_iterator_t const & right) const
   {
      return !(*this != right);
   }
   
   inline void edge_iterator_t::operator ++ ()
   {
      if(it_ != it_end_) 
      {
        ++it_;
        if (it_ == it_end_) 
            ++(*this);
      }
      else
      {
        ++cur_v_it_;
        if (cur_v_it_ != end_v_it_)
        {            
            it_ = graph_->get_vertex_edges((*cur_v_it_).get_id().vertex_in_graph_id_).first;
            it_end_ = graph_->get_vertex_edges((*cur_v_it_).get_id().vertex_in_graph_id_).second;
            ++(*this);
        }
      }
   }
   inline edge_t const edge_iterator_t::operator * () const
   {
      return edge_t(it_, (*cur_v_it_).get_id());
   }
   inline edge_t edge_iterator_t::operator * ()
   {
      return edge_t(it_, (*cur_v_it_).get_id());
   }
   inline bool edge_iterator_t::operator != (edge_iterator_t const & right) const
   {
      return it_ != right.it_;
   }
   inline bool edge_iterator_t::operator == (edge_iterator_t const & right) const
   {
      return !(*this != right);
   }
   
   inline void adj_vertices_iterator_t::operator ++ ()
   {
      ++it_;
   }
   inline vertex_t const & adj_vertices_iterator_t::operator * () const
   {
      return (*g_)[it_->get_target_vertex_id().vertex_in_graph_id_];
   }
   inline vertex_t& adj_vertices_iterator_t::operator * ()
   {
      return (*g_)[it_->get_target_vertex_id().vertex_in_graph_id_];
   }
   inline bool adj_vertices_iterator_t::operator != (adj_vertices_iterator_t const& right) const
   {
      return it_ != right.it_;
   }
   inline bool adj_vertices_iterator_t::operator == (adj_vertices_iterator_t const& right) const
   {
      return !(*this != right);
   }    
   
   inline void adj_edges_iterator_t::operator ++ ()
   {
      ++it_;
   }
   inline edge_t const adj_edges_iterator_t::operator * () const
   {
      return edge_t(it_, source_v_id_);
   }
   inline edge_t adj_edges_iterator_t::operator * ()
   {
      return edge_t(it_, source_v_id_);
   }
   inline bool adj_edges_iterator_t::operator != (adj_edges_iterator_t const & right) const
   {
      return it_ != right.it_;
   }   
   inline bool adj_edges_iterator_t::operator == (adj_edges_iterator_t const & right) const
   {
      return !(*this != right);
   }   
   inline vertex_iterator_pair_t vertices(graph_t& g)
   {
      return vertex_iterator_pair_t(vertex_iterator_t(g), vertex_iterator_t( &g[0] + g.get_vertex_count() ));
   }
   inline edge_iterator_pair_t edges(graph_t& g)
   {
      return edge_iterator_pair_t(edge_iterator_t(g), edge_iterator_t( g.get_vertex_edges(0).first + g.get_edge_count() ));
   }
   inline adj_edges_iterator_pair_t adj_edges(vertex_id_t source_v_id, graph_t& g)
   {
      return adj_edges_iterator_pair_t(
                     adj_edges_iterator_t(source_v_id, g), 
                     adj_edges_iterator_t(g.get_vertex_edges(source_v_id.vertex_in_graph_id_).second)
                     );
   }

   inline adj_vertices_iterator_pair_t adj_vertices(vertex_id_t source_v_id, graph_t& g)
   {
      return adj_vertices_iterator_pair_t(
                     adj_vertices_iterator_t(source_v_id, g), 
                     adj_vertices_iterator_t(g.get_vertex_edges(source_v_id.vertex_in_graph_id_).second)
                     );
   }

}